Skip to content

CI only for yas-run/yas#88 (keep output head and tail, on #86) — do not merge - #42

Closed
pcarrier wants to merge 4 commits into
ci-basefrom
keep-output
Closed

pcarrier wants to merge 4 commits into
ci-basefrom
keep-output

Conversation

@pcarrier

Copy link
Copy Markdown

Fork CI for yas-run#88 (yas-run Actions are stuck org-wide).

@pcarrier pcarrier changed the title CI: yas-run/yas#88 keep-output CI only for yas-run/yas#88 (keep output head and tail, on #86) — do not merge Sep 30, 2026
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Coverage

Crate Lines Functions Regions
alacritty-driver 85.6% (1081/1263) 89.4% (84/94) 89.3% (1746/1955)
browser 25.5% (309/1212) 30.4% (34/112) 27.7% (605/2183)
cli 31.8% (6517/20468) 32.8% (598/1824) 32.9% (9634/29263)
client 65.3% (4753/7278) 67.6% (614/908) 63.6% (6172/9697)
composite-transport 96.3% (526/546) 98.4% (60/61) 96.2% (884/919)
compositor 54.9% (11401/20763) 66.1% (833/1261) 54.7% (15787/28844)
desktop 78.4% (4460/5691) 71.6% (393/549) 75.1% (6211/8267)
edge 63.1% (800/1268) 50.9% (82/161) 58.0% (1043/1799)
fonts 77.3% (1257/1626) 82.7% (129/156) 78.9% (2424/3071)
fssync 85.5% (1601/1872) 85.4% (181/212) 86.7% (2821/3255)
git 70.4% (4462/6334) 68.5% (337/492) 67.3% (6313/9386)
guest 67.3% (6829/10148) 67.0% (488/728) 66.6% (8935/13416)
lsp 78.7% (3573/4542) 80.8% (336/416) 76.7% (5408/7054)
proxy 63.0% (1854/2943) 56.2% (180/320) 63.3% (2860/4521)
runtime-dir 93.6% (117/125) 100.0% (14/14) 94.8% (218/230)
sd-notify 73.9% (68/92) 100.0% (6/6) 83.2% (109/131)
server 70.7% (84017/118792) 73.2% (6094/8322) 68.7% (112475/163678)
ssh 67.2% (708/1054) 75.9% (85/112) 67.2% (1105/1645)
terminal-model 49.9% (314/629) 62.3% (38/61) 50.3% (505/1004)
uplink 94.2% (582/618) 92.6% (50/54) 93.1% (1062/1141)
webrtc-forwarder 33.6% (1321/3932) 44.9% (146/325) 36.0% (2279/6336)
webserver 80.7% (1490/1846) 81.1% (193/238) 83.2% (2551/3067)
website 35.1% (355/1012) 34.4% (53/154) 35.8% (607/1694)
xtask 0.0% (0/5149) 0.0% (0/131) 0.0% (0/9157)
yas 88.8% (27842/31363) 93.8% (2132/2272) 83.9% (43722/52130)
Total 66.3% (166237/250566) 69.3% (13160/18983) 64.7% (235476/363843)

…run#86)

* Report a spawned process's exit unasked: bash in one round trip

A SPAWN with the new opt-in flag REPORT_EXIT (16) gets its process's exit as
an EXIT Event (Process 0x0002, sensitive) once it is final: the record a WAIT
would return then. A command's SPAWN Result, output and exit thus all come
from one request, where a client had to send WAIT and wait a round trip more.

- Servers advertise it in a new optional family limit, LAUNCHER_FLAGS_EXTENDED
  (tag 19), since clients from before accept at most 12 in tag 11; a client sets
  REPORT_EXIT only when tag 19 offers it, so either side may be older.
- The report takes none of the session's pending WAITs, is sent once (a SPAWN
  retried under its operation ID shares it), and outlives the streams: when the
  spawning session's attachment goes before the exit (its streams dropped, their
  route failed), the server waits for the exit itself and still sends it.
- The streams go on at the pace of their credit, so the EXIT may arrive before
  their last bytes and CLOSE.
- yas-client sets the flag whenever offered; Process::wait/wait_timeout then
  take no request and keep the reported exit. Attached processes, and servers
  without the flag, still WAIT.

Tests (client_host): a_spawned_process_reports_its_exit_without_a_wait (with
the only WAIT held, a non-zero exit with stderr, output beyond the stream
buffer read while the exit is awaited, a signal, and another session's
attachment that still WAITs), and a_server_from_before_report_exit_is_waited_for
(ignored; YAS_OLD_SERVER=<yas without the flag>).

* Report an exit only from the attachment that saw it; WAIT once that goes

Review of yas-run#86: the server's fallback wait, for a REPORT_EXIT process whose
attachment went before its exit, bound the process again (a detached one's
slot was taken back and ATTACH answered CONFLICT), hung Process::wait when
that wait failed, and an attachment aborted mid-send lost the EXIT.

The fallback is gone: the attachment reports the exit, from a task of its
own so removing the attachment meanwhile cannot cut the EXIT short. When the
attachment goes first (a Transfer RESET on any of its streams, stdin
included, sent or received, or a DETACH) no EXIT comes, and yas-client
knows: its router marks the process's report lost, and Process::wait and
wait_timeout then WAIT, after taking an EXIT that already arrived.

* Make tag 19 a set of SPAWN flags whose unknown bits clients ignore

LAUNCHER_FLAGS_EXTENDED's hard maximum was 28, the flags it carries
today: a later server adding one would have failed the HELLO of every
client from this PR, as tag 11's maximum of 12 would have failed older
clients for REPORT_EXIT. Its hard maximum is now 65535 (any u16 of SPAWN
flags) and Limits::from_extensions keeps only the flags it knows, so the
next flag needs no new tag.
SPAWN_KEEP_OUTPUT (32), with REPORT_EXIT and SPAWN extension tag 4
[head_bytes, tail_bytes] (the tail at most 1 MiB), sends only the head and
the tail of each output stream. What comes between is dropped as the
server reads it, never held for the client's credit, so a command writing
far more than its client keeps runs at the speed of its pipe instead of
one window per round trip.

The cuts fall between characters as a WHATWG UTF-8 decoder with
replacement reads the whole stream (a JavaScript TextDecoder, Rust's
from_utf8_lossy), so decoding the head and the tail gives exactly the
characters they have within it. The EXIT event says what was dropped of
each stream (extension tags 1 and 2, OutputElision: offset, bytes, lines,
code points, UTF-16 units), so a client can say how much it did not get in
the units it counts.

The output reader waits for the owner only while the head goes out, keeps
the last tail_bytes in a ring, and sends them at the stream's end, or
before the exit is reported when the stream outlives it (a residue past
its grace, TERMINATE, a lost owner, a forced cleanup): flush_kept.

yas-client: Command::keep_output(head, tail), set where the server offers
it; Process::elided(stderr) once the exit came.
Review of yas-run#88: Output had no place for what KEEP_OUTPUT dropped, and
output() takes the process, so a kept command's head and tail came joined
with nothing to say a middle was missing. Output.elided now carries it
(the test's helper is output_limited again). And the new mod output_keep
line took mod process's #[cfg(any(unix, windows))].
protocol-fuzz found OutputElision::decode multiplying a decoded code point
count by two, which panics past u64::MAX / 2. Saturate instead: a count that
wide bounds nothing it could hold. Test the five counts' rules, prefixes, and
the widest values.
@pcarrier

pcarrier commented Oct 1, 2026

Copy link
Copy Markdown
Author

Upstream PR merged into yas-run/yas main (now dd33f04): this CI-only draft is done.

@pcarrier pcarrier closed this Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant